package com.apache.portal.common.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

import com.apache.portal.common.oscache.BaseOsCache;
import com.apache.portal.common.oscache.OsCacheOtherManager;
import com.apache.portal.weixin.core.manager.BeanFactory;
import com.apache.portal.weixin.core.manager.WxRecvMsgParser;
import com.apache.portal.weixin.entity.AccessToken;
import com.apache.portal.weixin.entity.WeixinUser;
import com.apache.portal.weixin.entity.recv.WxRecvMsg;
import com.apache.portal.weixin.entity.send.WxSendMsg;
import com.apache.uct.common.ToolsUtil;

/**
  * description: 验证解板工具类
  * @author Hou DaYu 创建时间：下午04:59:32
 */
public final class WeiXinTools {

	/**
	  * description: 合法信息验证
	  * @param signature 微信加密签名
	  * @param timestamp 时间戳
	  * @param nonce     随机数
	  * @return true为验证成功；false为验证失败
	 */
	public boolean access(String signature, String timestamp, String nonce) {
		List<String> ss = new ArrayList<String>();
		ss.add(timestamp);
		ss.add(nonce);
		ss.add(ToolsUtil.getInstance().getValueByKey("weixin_token"));

		Collections.sort(ss);

		StringBuilder builder = new StringBuilder();
		for (String s : ss) {
			builder.append(s);
		}
		return signature.equalsIgnoreCase(HashKit.sha1(builder.toString()));
	}

	/**
	  * description: 解析接收数据
	  * @param in 接收数据流
	  * @return 返回接收信息模型
	 */
	public WxRecvMsg recv(InputStream in) throws JDOMException, IOException {
		return parse(in);
	}

	/**
	  * description: 发送返回信息
	  * @param msg 返回信息模型
	  * @param out 信息输出流
	 */
	public void send(WxSendMsg msg, OutputStream out) throws JDOMException, IOException {
		Document doc = parse(msg);
		if (null != doc) {
			new XMLOutputter().output(doc, out);
		} else {
			Logger.getAnonymousLogger().warning("发送消息时,解析出dom为空 msg :" + msg);
		}
	}

	/**
	  * description: 转换信息
	  * @param msg 接收信息模型
	  * @return 返回输出信息模型
	 */
	public WxSendMsg builderSendByRecv(WxRecvMsg msg) {
		WxRecvMsg m = new WxRecvMsg(msg);
		String from = m.getFromUser();
		m.setFromUser(m.getToUser());
		m.setToUser(from);
		m.setCreateDt((System.currentTimeMillis() / 1000) + "");
		return new WxSendMsg(m);
	}

	/**
	  * description: 转换消息模型
	  * @param in 消息输入流
	  * @return 返回消息模型
	 */
	public WxRecvMsg parse(InputStream in) throws JDOMException, IOException {
		Document dom = new SAXBuilder().build(in);
		Element msgType = dom.getRootElement().getChild("MsgType");
		if (null != msgType) {
			String txt = msgType.getText().toLowerCase();
			WxRecvMsgParser parser = BeanFactory.getInstance().getBeansParser(txt);
			if (null != parser) {
				return parser.parser(dom);
			} else {
				System.out.println(txt);
			}
		}
		return null;
	}

	/**
	  * description: 转成docment模型
	  * @param msg 消息模型
	  * @return
	 */
	public Document parse(WxSendMsg msg) throws JDOMException {
		return msg.toDocument();
	}

	/**
	 * 获取access_token
	 */
	public AccessToken getAccessToken() {
		String appid = ToolsUtil.getInstance().getValueByKey("ius_appid");
		BaseOsCache oscache = OsCacheOtherManager.getInstance().getBaseOsCache("weixin_token_", 60 * 90);
		String cacheKey = "accessToken_" + appid;
		Object obj = oscache.get(cacheKey);
		if (!ToolsUtil.isEmpty(obj)) {
			return (AccessToken) obj;
		} else {
			AccessToken accessToken = new AccessToken();
			String appsecret = ToolsUtil.getInstance().getValueByKey("ius_AppSecret");
			String requestUrl = ToolsUtil.getInstance().getValueByKey("access_token_url").replace("APPID", appid)
					.replace("APPSECRET", appsecret);
			Map<String, String> params = new HashMap<String, String>();
			params.put("resultType", "json");
			JSONObject jsonObject = (JSONObject) HttpRequestTools.getInstance().httpRequest(requestUrl, "GET", null,
					params);
			// 如果请求成功
			if (null != jsonObject) {
				try {
					accessToken = new AccessToken();
					accessToken.setToken(jsonObject.getString("access_token"));
					accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
					oscache.put(cacheKey, accessToken);
				} catch (JSONException e) {
					System.out.println("获取token失败 errcode:" + jsonObject.getInt("errcode"));
				}
			}
			return accessToken;
		}
	}

	/**
	  * description:  获取用户信息
	 */
	public WeixinUser getUserInfo(String openId) {
		String user_info = ToolsUtil.getInstance().getValueByKey("user_info_url");
		String url = user_info.replace("OPENID", openId);
		AccessToken token = getAccessToken();
		url = url.replaceAll("ACCESS_TOKEN", token.getToken());
		Map<String, String> params = new HashMap<String, String>();
		params.put("resultType", "json");
		JSONObject jsonObject = (JSONObject) HttpRequestTools.getInstance().httpRequest(url, "GET", null, params);
		WeixinUser user = null;
		if (null != jsonObject) {
			user = new WeixinUser();
			user.setSubscribe(Integer.valueOf(jsonObject.get("subscribe").toString()));
			user.setOpenid(String.valueOf(jsonObject.get("openid")));
			user.setCity(String.valueOf(jsonObject.get("city")));
			user.setCountry(String.valueOf(jsonObject.get("country")));
			user.setProvince(String.valueOf(jsonObject.get("province")));
			user.setHeadimgurl(String.valueOf(jsonObject.get("headimgurl")));
			user.setNickname(String.valueOf(jsonObject.get("nickname")));
			int sex = Integer.valueOf(jsonObject.get("sex").toString());
			user.setSex(sex);
		}
		return user;
	}

	/**
	 * description:  推送消息
	 * @param json   推送内容
	 * @author Hou Dayu  
	 * @update 2014-8-18
	 */
	public void sendInfo(String json) {
		String send_url = ToolsUtil.getInstance().getValueByKey("send_url");
		AccessToken token = getAccessToken();
		String url = send_url.replaceAll("ACCESS_TOKEN", token.getToken());
		DefaultHttpClient client = new DefaultHttpClient();
		HttpPost post = new HttpPost(url);
		try {
			StringEntity s = new StringEntity(json);
			s.setContentEncoding("UTF-8");
			s.setContentType("application/json");
			post.setEntity(s);
			HttpResponse res = client.execute(post);
			if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				HttpEntity entity = res.getEntity();
				System.out.println(EntityUtils.toString(entity, "utf-8"));
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 
	 * @param mediaId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> getMedia(String mediaId, String openId) {
		String media_get_url = ToolsUtil.getInstance().getValueByKey("media_get_url");
		String url = media_get_url.replace("MEDIA_ID", mediaId);
		AccessToken token = getAccessToken();
		url = url.replaceAll("ACCESS_TOKEN", token.getToken());
		Map<String, String> params = new HashMap<String, String>();
		params.put("resultType", "pic");
		params.put("openId", openId);
		Map<String, String> fileMap = (Map) HttpRequestTools.getInstance().httpRequest(url, "GET", "", params);
		return fileMap;
	}

	public int sendMsg(String openId, String content, String type, String msgtype) {
		int result = 0;
		String sendUrl = "";
		String jsonMenu = "";
		if ("openId".equalsIgnoreCase(type)) {
			sendUrl = ToolsUtil.getInstance().getValueByKey("send_url");
			if ("news".equalsIgnoreCase(msgtype)) {
			} else {
				jsonMenu = "{\"touser\":[" + openId + "],\"msgtype\":\"text\",\"text\":{\"content\":\"" + content
						+ "\"}}";
			}
		} else if ("crm".equalsIgnoreCase(type)) {
			sendUrl = ToolsUtil.getInstance().getValueByKey("crm_url");
			jsonMenu = "{\"touser\":" + openId + ",\"msgtype\":\"text\",\"text\":{\"content\":\"" + content + "\"}}";
			if ("news".equalsIgnoreCase(msgtype)) {
				jsonMenu = "{\"touser\":" + openId + ",\"msgtype\":\"news\"," + "\"news\":{\"articles\": [{" + content
						+ "}]}}";
			} else {
				jsonMenu = "{\"touser\":" + openId + ",\"msgtype\":\"text\",\"text\":{\"content\":\"" + content
						+ "\"}}";
			}
		} else {
			sendUrl = ToolsUtil.getInstance().getValueByKey("qunfa_url");//群发
			if ("news".equalsIgnoreCase(msgtype)) {
			} else {
				jsonMenu = "{\"filter\":{\"is_to_all\":true}, \"text\":{\"content\":\"" + content
						+ "\"}, \"msgtype\":\"text\"}";//,\"tag_id\":0
			}
		}
		AccessToken token = getAccessToken();
		String url = sendUrl.replaceAll("ACCESS_TOKEN", token.getToken());
		Map<String, String> params = new HashMap<String, String>();
		params.put("resultType", "json");
		JSONObject jsonObject = (JSONObject) HttpRequestTools.getInstance().httpRequest(url, "GET", null, params);
		if (null != jsonObject) {
			if (0 != jsonObject.getInt("errcode")) {
				result = jsonObject.getInt("errcode");
				//创建菜单失败, jsonObject.getInt("errcode"), jsonObject.getString("errmsg")
				System.out.println("推送消息失败  errcode=" + result);
			}
		}
		return result;
	}

}
